package solutions;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import org.pi4.locutil.GeoPosition;
import org.pi4.locutil.io.TraceGenerator;
import org.pi4.locutil.trace.Parser;
import org.pi4.locutil.trace.TraceEntry;

public class MainAlgorithmRunner {
	static final int offlineSize = 25;
	static final int onlineSize = 5;
	static final String wifiPositionsPath = "data/MU.AP.positions";

	public static void main(String[] args) throws Exception {
		if (args.length == 0)
			throw new Exception("wrong input exception!");

		String arg = args[0];

		Parser offlineParser = new Parser(new File(
				"data/MU.1.5meters.offline.trace"));
		Parser onlineParser = new Parser(new File(
				"data/MU.1.5meters.online.trace"));
		List<Double> differences = new ArrayList<Double>(offlineSize);

		TraceGenerator tg = new TraceGenerator(offlineParser, onlineParser,
				offlineSize, onlineSize);
		tg.generate();

		TraceEstimater estimater = null;
		if (arg.equals("FingerPrintingNN")) {
			estimater = new FingerPrintingNN(tg, differences);
		} else if (arg.equals("ModelNN")) {
			List<TraceEntry> apPositions = WifiPositionsParser
					.parser(wifiPositionsPath);
			estimater = new ModelNN(tg, differences, apPositions);
		} else if (arg.equals("FingerPrintingKNN")) {
			int k = Integer.parseInt(args[1]);
			estimater = new FingerPrintingKNN(tg, differences, k);
		} else if (arg.equals("ModelKNN")) {
			int k = Integer.parseInt(args[1]);
			List<TraceEntry> apPositions = WifiPositionsParser
					.parser(wifiPositionsPath);
			estimater = new ModelKNN(tg, differences, k, apPositions);
		} else {
			throw new Exception("wrong input exception!");
		}
		BufferedWriter writer = new BufferedWriter(new FileWriter(new File(arg
				+ ".txt")));

		List<TraceEntry> onlineTrace = tg.getOnline();
		writer.write("Estimate: 	 	 Real Position:");
		writer.newLine();
		estimater.buildRadioMap(tg.getOffline());

		for (TraceEntry entry : onlineTrace) {
			GeoPosition estimatePos = estimater.estimatePosition(entry);
			double euclidianDistance = estimatePos.distance(entry
					.getGeoPosition());

			writer.write(estimatePos.toStringWithoutOrientation() + "	 ;	 "
					+ entry.getGeoPosition().toStringWithoutOrientation());
			writer.newLine();
			differences.add(euclidianDistance);
		}

		estimater.printStats();
		writer.close();
	}

	public interface TraceEstimater {
		public GeoPosition estimatePosition(TraceEntry entry);

		public void buildRadioMap(List<TraceEntry> onlineTracer);

		public List<EntryWithMACsAndAverages> getRadioMap();

		public void printStats();
	}
}
